let jsonData = null;
let currentPath = '';

// Show message
function showMessage(message, type = 'error') {
    const messageEl = document.getElementById('json-message');
    messageEl.textContent = message;
    messageEl.className = `message ${type} show`;
    setTimeout(() => messageEl.classList.remove('show'), 3000);
}

// Handle paste event - auto format
function handlePaste() {
    setTimeout(() => {
        formatJSON();
    }, 100);
}

// Toggle search box
function toggleSearch() {
    const searchBox = document.getElementById('json-search-box');
    if (searchBox.style.display === 'none') {
        searchBox.style.display = 'block';
        document.getElementById('json-search').focus();
    } else {
        searchBox.style.display = 'none';
        document.getElementById('json-search').value = '';
        searchJSON();
    }
}

// Format JSON
function formatJSON() {
    const input = document.getElementById('json-input').value.trim();
    if (!input) {
        showMessage('请输入 JSON 数据');
        return;
    }

    try {
        jsonData = JSON.parse(input);
        const rootName = document.getElementById('root-name').value.trim() || 'data';
        renderJSONTree(jsonData, rootName);
    } catch (err) {
        showMessage(`JSON 格式错误: ${err.message}`);
        document.getElementById('json-tree').innerHTML = '';
    }
}

// Render JSON as interactive tree
function renderJSONTree(data, rootName = 'data') {
    const treeEl = document.getElementById('json-tree');
    treeEl.innerHTML = '';
    treeEl.appendChild(createJSONElement(data, rootName));
}

// Create JSON element with proper indentation and collapsible structure
function createJSONElement(value, path, key = null, indent = 0, isLast = true) {
    const container = document.createElement('div');
    const indentStr = '  '.repeat(indent);

    if (value === null) {
        const line = document.createElement('div');
        line.className = 'json-line';
        line.innerHTML = indentStr + createKeyValue(key, '<span class="json-null">null</span>', path, isLast);
        container.appendChild(line);
    } else if (typeof value === 'object' && !Array.isArray(value)) {
        // Object
        const entries = Object.entries(value);
        const hasChildren = entries.length > 0;
        const nodeId = 'node-' + Math.random().toString(36).substr(2, 9);

        const openLine = document.createElement('div');
        openLine.className = `json-line ${hasChildren ? 'has-children' : ''}`;
        
        let openHtml = '';
        if (hasChildren) {
            openHtml += `<span class="collapse-btn" onclick="toggleNode('${nodeId}')">−</span>`;
        }
        openHtml += indentStr;
        if (key !== null) {
            openHtml += createKeySpanSimple(key) + ': ';
        }
        openHtml += '<span class="json-bracket">{</span>';
        if (hasChildren) {
            openHtml += `<span style="color: #999; font-size: 12px; margin-left: 8px;">${entries.length} items</span>`;
        }
        openHtml += `<span class="json-ellipsis" id="ellipsis-${nodeId}" style="display:none;"> ... </span>`;
        openLine.innerHTML = openHtml;
        container.appendChild(openLine);

        if (hasChildren) {
            const childrenContainer = document.createElement('div');
            childrenContainer.className = 'json-children';
            childrenContainer.id = nodeId;

            entries.forEach(([k, v], index) => {
                const newPath = path ? `${path}.${k}` : k;
                const childIsLast = index === entries.length - 1;
                const childEl = createJSONElement(v, newPath, k, indent + 1, childIsLast);
                childrenContainer.appendChild(childEl);
            });

            container.appendChild(childrenContainer);

            const closeLine = document.createElement('div');
            closeLine.className = 'json-line';
            closeLine.innerHTML = indentStr + '<span class="json-bracket">}</span>' + (isLast ? '' : ',');
            container.appendChild(closeLine);
        }
    } else if (Array.isArray(value)) {
        // Array
        const hasChildren = value.length > 0;
        const nodeId = 'node-' + Math.random().toString(36).substr(2, 9);

        const openLine = document.createElement('div');
        openLine.className = `json-line ${hasChildren ? 'has-children' : ''}`;
        
        let openHtml = '';
        if (hasChildren) {
            openHtml += `<span class="collapse-btn" onclick="toggleNode('${nodeId}')">−</span>`;
        }
        openHtml += indentStr;
        if (key !== null) {
            openHtml += createKeySpanSimple(key) + ': ';
        }
        openHtml += '<span class="json-bracket">[</span>';
        if (hasChildren) {
            openHtml += `<span style="color: #999; font-size: 12px; margin-left: 8px;">${value.length} items</span>`;
        }
        openHtml += `<span class="json-ellipsis" id="ellipsis-${nodeId}" style="display:none;"> ... </span>`;
        openLine.innerHTML = openHtml;
        container.appendChild(openLine);

        if (hasChildren) {
            const childrenContainer = document.createElement('div');
            childrenContainer.className = 'json-children';
            childrenContainer.id = nodeId;

            value.forEach((item, index) => {
                const newPath = `${path}[${index}]`;
                const childIsLast = index === value.length - 1;
                const childEl = createJSONElement(item, newPath, null, indent + 1, childIsLast);
                childrenContainer.appendChild(childEl);
            });

            container.appendChild(childrenContainer);

            const closeLine = document.createElement('div');
            closeLine.className = 'json-line';
            closeLine.innerHTML = indentStr + '<span class="json-bracket">]</span>' + (isLast ? '' : ',');
            container.appendChild(closeLine);
        }
    } else {
        // Primitive value
        const line = document.createElement('div');
        line.className = 'json-line';
        const pathId = 'path-' + Math.random().toString(36).substr(2, 9);
        line.innerHTML = indentStr + createKeyValue(key, formatValue(value), path, isLast, pathId);
        // 给整行添加点击事件
        if (key !== null) {
            line.onclick = function(e) {
                // 如果点击的是按钮或键名，不触发
                if (e.target.tagName === 'BUTTON' || e.target.classList.contains('json-key')) {
                    return;
                }
                togglePath(pathId);
            };
            line.style.cursor = 'pointer';
        }
        container.appendChild(line);
    }

    return container;
}

// Toggle individual node
function toggleNode(nodeId) {
    const childrenEl = document.getElementById(nodeId);
    const ellipsisEl = document.getElementById('ellipsis-' + nodeId);
    const btn = event.target;
    
    if (childrenEl.classList.contains('collapsed')) {
        childrenEl.classList.remove('collapsed');
        ellipsisEl.style.display = 'none';
        btn.textContent = '−';
    } else {
        childrenEl.classList.add('collapsed');
        ellipsisEl.style.display = 'inline';
        btn.textContent = '+';
    }
}

// Create simple key span (for objects/arrays)
function createKeySpanSimple(key) {
    return `<span class="json-key">"${escapeHtml(key)}"</span>`;
}

// Create key-value pair
function createKeyValue(key, valueHTML, path, isLast, pathId) {
    let html = '';
    if (key !== null) {
        const escapedPath = escapeHtml(path);
        const escapedPathAttr = path.replace(/'/g, "\\'").replace(/"/g, '&quot;');
        const escapedKey = key.replace(/'/g, "\\'").replace(/"/g, '&quot;');
        
        // 键名可点击复制
        html += `<span class="json-key" onclick="event.stopPropagation(); copyText('${escapedKey}', this)" title="点击复制键名">"${escapeHtml(key)}"</span>`;
        html += ': ';
        html += valueHTML;
        if (!isLast) html += ',';
        // 显示：先复制按钮，再路径
        html += `<span id="${pathId}" class="json-key-path" style="display:none;"> <button onclick="event.stopPropagation(); copyPathFromButton(this, '${escapedPathAttr}')">复制</button> <span>${escapedPath}</span></span>`;
    } else {
        html += valueHTML;
        if (!isLast) html += ',';
    }
    return html;
}

// Toggle path display
function togglePath(pathId) {
    document.querySelectorAll('.json-key-path').forEach(el => {
        if (el.id !== pathId) el.style.display = 'none';
    });
    const pathEl = document.getElementById(pathId);
    if (pathEl) {
        pathEl.style.display = pathEl.style.display === 'none' ? 'inline' : 'none';
    }
}

// Copy path from button
async function copyPathFromButton(button, path) {
    try {
        await navigator.clipboard.writeText(path);
        button.textContent = '✓ 已复制';
        button.classList.add('copied');
        setTimeout(() => {
            button.textContent = '复制';
            button.classList.remove('copied');
        }, 2000);
    } catch (err) {
        button.textContent = '失败';
        setTimeout(() => {
            button.textContent = '复制';
        }, 2000);
    }
}

// Copy text (for key or value)
async function copyText(text, element) {
    try {
        await navigator.clipboard.writeText(text);
        const originalBg = element.style.backgroundColor;
        element.style.backgroundColor = '#d5f4e6';
        setTimeout(() => {
            element.style.backgroundColor = originalBg;
        }, 300);
    } catch (err) {
        console.error('复制失败:', err);
    }
}

// Format primitive value
function formatValue(value) {
    const escapedValue = String(value).replace(/'/g, "\\'").replace(/"/g, '&quot;');
    
    if (typeof value === 'string') {
        return `<span class="json-string" onclick="event.stopPropagation(); copyText('${escapeHtml(value).replace(/'/g, "\\'")}', this)" title="点击复制值">"${escapeHtml(value)}"</span>`;
    } else if (typeof value === 'number') {
        return `<span class="json-number" onclick="event.stopPropagation(); copyText('${value}', this)" title="点击复制值">${value}</span>`;
    } else if (typeof value === 'boolean') {
        return `<span class="json-boolean" onclick="event.stopPropagation(); copyText('${value}', this)" title="点击复制值">${value}</span>`;
    }
    return value;
}

// Escape HTML
function escapeHtml(text) {
    const div = document.createElement('div');
    div.textContent = text;
    return div.innerHTML;
}

// Search JSON
let searchMatches = [];
let currentMatchIndex = 0;

function searchJSON() {
    const searchTerm = document.getElementById('json-search').value;
    const treeEl = document.getElementById('json-tree');
    const countEl = document.getElementById('search-count');

    // 清除之前的高亮 - 恢复原始内容
    treeEl.querySelectorAll('.json-key, .json-string, .json-number, .json-boolean').forEach(el => {
        if (el.dataset.originalText) {
            el.innerHTML = el.dataset.originalText;
            delete el.dataset.originalText;
        }
    });

    if (!searchTerm) {
        searchMatches = [];
        currentMatchIndex = 0;
        countEl.textContent = '';
        return;
    }

    searchMatches = [];
    
    // 搜索所有文本节点
    treeEl.querySelectorAll('.json-key, .json-string, .json-number, .json-boolean').forEach(el => {
        const text = el.textContent;
        const lowerText = text.toLowerCase();
        const lowerSearch = searchTerm.toLowerCase();
        
        if (lowerText.includes(lowerSearch)) {
            // 保存原始文本
            if (!el.dataset.originalText) {
                el.dataset.originalText = el.innerHTML;
            }
            
            // 高亮匹配的文本部分
            const regex = new RegExp(`(${escapeRegex(searchTerm)})`, 'gi');
            const highlightedHTML = text.replace(regex, '<mark class="search-match">$1</mark>');
            el.innerHTML = highlightedHTML;
            
            // 收集所有高亮的 mark 元素
            el.querySelectorAll('.search-match').forEach(mark => {
                searchMatches.push(mark);
            });
        }
    });

    if (searchMatches.length > 0) {
        currentMatchIndex = 0;
        countEl.textContent = `1/${searchMatches.length}`;
        highlightCurrentMatch();
    } else {
        countEl.textContent = '0 个结果';
    }
}

function highlightCurrentMatch() {
    if (searchMatches.length === 0) return;

    // 清除所有当前高亮
    searchMatches.forEach(el => {
        el.classList.remove('search-current');
    });

    // 高亮当前匹配项
    const current = searchMatches[currentMatchIndex];
    current.classList.add('search-current');
    current.scrollIntoView({ behavior: 'smooth', block: 'center' });

    document.getElementById('search-count').textContent = `${currentMatchIndex + 1}/${searchMatches.length}`;
}

// 转义正则表达式特殊字符
function escapeRegex(string) {
    return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}

function searchNext() {
    if (searchMatches.length === 0) return;
    currentMatchIndex = (currentMatchIndex + 1) % searchMatches.length;
    highlightCurrentMatch();
}

function searchPrev() {
    if (searchMatches.length === 0) return;
    currentMatchIndex = (currentMatchIndex - 1 + searchMatches.length) % searchMatches.length;
    highlightCurrentMatch();
}

// Clear JSON
function clearJSON() {
    document.getElementById('json-input').value = '';
    document.getElementById('json-tree').innerHTML = '';
    document.getElementById('json-search').value = '';
    document.getElementById('json-search-box').style.display = 'none';
    jsonData = null;
    currentPath = '';
}

// Toggle fullscreen
function toggleFullscreen() {
    const panel = document.querySelector('.main-content');
    if (!document.fullscreenElement) {
        panel.requestFullscreen().catch(err => {
            alert('无法进入全屏模式');
        });
    } else {
        document.exitFullscreen();
    }
}

// Collapse all nodes
function collapseAll() {
    document.querySelectorAll('.json-children').forEach(el => {
        el.classList.add('collapsed');
    });
    document.querySelectorAll('.json-ellipsis').forEach(el => {
        el.style.display = 'inline';
    });
    document.querySelectorAll('.collapse-btn').forEach(btn => {
        btn.textContent = '+';
    });
}

// Expand all nodes
function expandAll() {
    document.querySelectorAll('.json-children').forEach(el => {
        el.classList.remove('collapsed');
    });
    document.querySelectorAll('.json-ellipsis').forEach(el => {
        el.style.display = 'none';
    });
    document.querySelectorAll('.collapse-btn').forEach(btn => {
        btn.textContent = '−';
    });
}

// Sort JSON
function sortJSON() {
    if (!jsonData) {
        alert('请先格式化 JSON');
        return;
    }
    try {
        const sorted = sortObjectKeys(jsonData);
        jsonData = sorted;
        const rootName = document.getElementById('root-name').value.trim() || 'data';
        renderJSONTree(sorted, rootName);
        showMessage('JSON 已排序', 'success');
    } catch (err) {
        alert('排序失败: ' + err.message);
    }
}

function sortObjectKeys(obj) {
    if (Array.isArray(obj)) {
        return obj.map(item => sortObjectKeys(item));
    } else if (obj !== null && typeof obj === 'object') {
        const sorted = {};
        Object.keys(obj).sort().forEach(key => {
            sorted[key] = sortObjectKeys(obj[key]);
        });
        return sorted;
    }
    return obj;
}

// Compress JSON result
function compressJSONResult() {
    if (!jsonData) {
        alert('请先格式化 JSON');
        return;
    }
    const compressed = JSON.stringify(jsonData);
    document.getElementById('json-tree').textContent = compressed;
    showMessage('JSON 已压缩', 'success');
}

// Copy JSON tree
async function copyJSONTree() {
    if (!jsonData) {
        alert('没有可复制的内容');
        return;
    }
    try {
        const text = JSON.stringify(jsonData, null, 2);
        await navigator.clipboard.writeText(text);
        showMessage('已复制到剪贴板', 'success');
    } catch (err) {
        alert('复制失败');
    }
}
